/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 combat_creature.h

	$Header: /heroes4/combat_creature.h $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "combat_sounds.h"

#include "adv_actor_action.h"
#include "combat_actor_action.h"
#include "creature_ability.h"
#include "creature_type.h"
#include "enum_operations.h"
#include "hero.h"
#include "hero_class_properties.h"
#include "sound.h"
#include "spell_properties.h"
#include "town_type.h"

// ----------------------------------------------------------------------------
// get a sound for a creature
// ----------------------------------------------------------------------------
static t_sound_ptr get_sound( t_creature_type creature, t_combat_actor_action_id action )
{
	static bool          initialized = false;
	static t_sound_cache caches[k_creature_type_count][k_combat_actor_action_count];

	if (!initialized)
	{
		t_creature_type          index;
		t_combat_actor_action_id id;
		std::string              name;
		
		for (index = t_creature_type(0); index < k_creature_type_count; enum_incr(index))
		{
			for (id = t_combat_actor_action_id(0); id < k_combat_actor_action_count; 
			     enum_incr(id))
			{
				name = get_keyword( index );
				name += ".";
				name += get_combat_actor_action_name( id );
				caches[index][id] = t_sound_cache( name );
			}
		}
		initialized = true;
	}
	
	t_sound_ptr result = caches[creature][action].get();

	if (result == 0)
		if ( action == k_combat_actor_action_melee_down 
			 || action == k_combat_actor_action_melee_up)
			return get_sound( creature, k_combat_actor_action_melee );
		
	return result;
}

// --------------------------------------------------------
// get an sound based on a hero's alignment and traits
// --------------------------------------------------------
static t_sound_ptr get_sound( t_town_type alignment,
							  bool		  is_spellcaster,
							  bool        has_archery,
							  bool		  is_male,
							  t_combat_actor_action_id action)
{
	static bool initialized = false;
	t_hero_combat_model_type	type;

	static t_sound_cache caches[k_town_type_count][k_hero_combat_model_count][2][k_combat_actor_action_count];
	
	if (!initialized)
	{
		t_town_type					town;
		std::string					base_name;
		std::string					name;
		int							sex;
		t_combat_actor_action_id	id;


		for (town = t_town_type(0); town < k_town_type_count; enum_incr(town))
		{
			for (type = t_hero_combat_model_type(0); type < k_hero_combat_model_count; 
			     enum_incr(type))
			{
				for (sex = 0; sex < 2; sex++)
				{
					base_name = get_combat_type_keyword( town, type, sex == 1);
					for (id = t_combat_actor_action_id(0); id < k_combat_actor_action_count; 
						 enum_incr(id))
					{
						name = base_name;
						name += ".";
						name += get_combat_actor_action_name( id );
						caches[town][type][sex][id] = t_sound_cache( name );
					}
				}
			}
		}
		initialized = true;
	}

	if (is_spellcaster && alignment != k_town_might)
		type = k_model_spellcaster;
	else if (has_archery)
		type = k_model_archer;
	else
		type = k_model_fighter;

	t_sound_ptr result = caches[alignment][type][is_male][action].get();

	if (result == 0)
		result = get_sound( k_mage, action );
	return result;
}

// --------------------------------------------------------
// get an sound from a stack
// --------------------------------------------------------
t_sound_ptr get_combat_sound( t_creature_stack const& stack, t_combat_actor_action_id action )
{
	t_hero const* hero = stack.get_hero();

	if (hero != 0)
		return get_sound( hero->get_alignment(), hero->uses_spellcaster_model(),
			              hero->has_ability( k_ability_ranged ), 
						  hero->is_male(), action );
	return get_sound( stack.get_creature_type(), action );
}

// --------------------------------------------------------
// get an sound from a stack
// --------------------------------------------------------
t_sound_ptr get_combat_sound( t_creature_stack const& stack, t_adv_actor_action_id action )
{
	t_combat_actor_action_id id;

	// map adventure action to related combat action
	switch( action )
	{
		case k_adv_actor_action_wait:
			id = k_combat_actor_action_wait;
			break;
		case k_adv_actor_action_fidget:
			id = k_combat_actor_action_fidget;
			break;
		case k_adv_actor_action_prewalk:
			id = k_combat_actor_action_prewalk;
			break;
		case k_adv_actor_action_walk:
			id = k_combat_actor_action_walk;
			break;
		case k_adv_actor_action_postwalk:
			id = k_combat_actor_action_postwalk;
			break;
		case k_adv_actor_action_attack:
			id = k_combat_actor_action_melee;
			break;
	}
	
	return get_combat_sound( stack, id );
}

// --------------------------------------------------------
// get an sound from a spell
// --------------------------------------------------------
t_sound_ptr get_combat_sound( t_spell spell )
{
	static bool          initialized = false;
	static t_sound_cache caches[k_spell_effect_count];

	if (!initialized)
	{
		t_spell     spell;
		std::string name;

		for (spell = t_spell(0); spell < k_spell_effect_count; enum_incr( spell ))
		{
			name = "spell.";
			name += get_spell_keyword( spell );
			caches[spell] = t_sound_cache( name );
		}
		initialized = true;
	}

	t_sound_ptr result = caches[spell].get();

	if (result == 0)
		result = caches[k_spell_curse].get();
	return result;
}
